package net.pimpas.web.tests.bb;

import net.pimpas.framework.PimpasFramework;
import net.pimpas.resourcebundle.exception.MessageKeyNotFoundException;
import net.pimpas.resourcebundle.exception.ResourceBundleNotFoundException;
import net.pimpas.resourcebundle.serviceprovider.ResourceBundleServiceProvider;
import net.pimpas.resourcebundle.serviceprovider.ResourceBundleServiceProviderFactoryImpl;
import net.pimpas.resourcebundle.serviceprovider.ResourceBundleServiceProviderType;
import net.pimpas.security.serviceprovider.SecurityServiceProvider;
import net.pimpas.security.serviceprovider.SecurityServiceProviderFactoryImpl;
import net.pimpas.security.serviceprovider.auth.Subject;
import net.pimpas.security.serviceprovider.auth.login.LoginException;
import net.pimpas.security.serviceprovider.auth.login.LoginNameException;
import net.pimpas.security.serviceprovider.auth.login.LoginPasswordException;
import net.pimpas.security.serviceprovider.auth.login.LoginStatus;
import net.pimpas.security.serviceprovider.auth.login.LoginUserAlreadyLoggedException;
import net.pimpas.security.serviceprovider.auth.login.LoginUserNotLoggedInException;
import net.pimpas.security.serviceprovider.auth.login.callback.Callback;
import net.pimpas.security.serviceprovider.auth.login.callback.CallbackListener;
import net.pimpas.security.serviceprovider.auth.login.callback.name.NameCallback;
import net.pimpas.security.serviceprovider.auth.login.callback.password.PasswordCallback;
import net.pimpas.util.reflection.ReflectionUtil;
import net.pimpas.web.jsf.managedbean.ManagedBeanAnnotation;
import net.pimpas.web.tests.auth.login.LoginUtils;
import net.pimpas.web.tests.entitys.user.User;

@ManagedBeanAnnotation(beanName="loginScreen")
public class LoginBB {

	private String login;
	private String password;
	private String loginMessage;
	private boolean loggedIn;
	
	public String getLogin() {
		return login;
	}
	public void setLogin(String login) {
		this.login = login;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
	public boolean isLoggedIn( ) {
		return this.loggedIn;
	}
	
	private User getLoggedUser( ) {
		Subject subject = (Subject) PimpasFramework.getCurrentInstance().getContext().getSession().getAttribute(LoginUtils.USER_KEY);
		return (User) ((subject==null) ? null : subject.getPrincipal(LoginUtils.USER_SUBJECT).getObject());
	}
	
	@SuppressWarnings("unchecked")
	public String doLogin( ) {
		SecurityServiceProvider security = 
			SecurityServiceProviderFactoryImpl.getSecurityServiceProvider();
		ResourceBundleServiceProvider bundle = 
			ResourceBundleServiceProviderFactoryImpl.getResourceBundleServiceProvider();
		LoginStatus state = null;
		try {
			state = security.authenticate("UserLogin", new LoginListener());
		} catch (LoginException e) {
			if(e instanceof LoginNameException || e instanceof LoginPasswordException || e instanceof LoginUserAlreadyLoggedException)
				this.setLoginMessage(e.getMessage());
			else
				throw new RuntimeException(e);
		}
		if(state != null && state.equals(LoginStatus.SUCCESS)) {
			User user = this.getLoggedUser();
			this.setLoggedIn(true);
			try {
				this.setLoginMessage(bundle.getMessage(this.getClass(), "loginSuccessfull", ResourceBundleServiceProviderType.INFO, user.getLogin()));
			} catch (ResourceBundleNotFoundException e) {
			} catch (MessageKeyNotFoundException e) {
			}
		}
		
		return "";
	}
	
	public String doLogoff( ) {
		SecurityServiceProvider security = 
			SecurityServiceProviderFactoryImpl.getSecurityServiceProvider();
		ResourceBundleServiceProvider bundle = 
			ResourceBundleServiceProviderFactoryImpl.getResourceBundleServiceProvider();
		LoginStatus state = null;
		User user = this.getLoggedUser();
		try {
			state = security.unAuthenticate("UserLogin", new LoginListener());
		} catch(LoginException e) {
			if(e instanceof LoginUserNotLoggedInException) {
				this.setLoginMessage(e.getMessage());
			} else
				throw new RuntimeException(e);
		}
		if(state != null && state.equals(LoginStatus.SUCCESS)) {
			this.setLoggedIn(false);
			try {
				this.setLoginMessage(bundle.getMessage(this.getClass(), "logoffSuccesfull", ResourceBundleServiceProviderType.INFO, user.getLogin()));
			} catch (ResourceBundleNotFoundException e) {
			} catch (MessageKeyNotFoundException e) {
			}
		}
		
		return "";
	}
	
	public class LoginListener implements CallbackListener {

		public void processCallback(Callback callback) {
			if(ReflectionUtil.isSubclass(callback.getClass(), NameCallback.class))
				((NameCallback)callback).setInputName(getLogin( ));
			else if(ReflectionUtil.isSubclass(callback.getClass(), PasswordCallback.class))
				((PasswordCallback)callback).setPassword((getPassword()==null) ? "".toCharArray() : getPassword().toCharArray());
		}
	}

	public String getLoginMessage() {
		return loginMessage;
	}
	public void setLoginMessage(String loginMessage) {
		this.loginMessage = loginMessage;
	}
	public void setLoggedIn(boolean loggedIn) {
		this.loggedIn = loggedIn;
	}
}